package cn.edu.scau.cmi.ema.service.base;

import cn.edu.scau.cmi.ema.base.CmiPagination;
import cn.edu.scau.cmi.ema.util.CmiHibernateProxyUtil;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import org.springframework.stereotype.Component;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.Consumer;


@Component
public class CmiPsonService {

//    public enum Flag {
//        FIRST, SECOND, THIRD;
//    }

    private int customePsonDepth;//用户需要的深度。

//    private int psonDepth = 1;

//    private int defaultPsonDepth = 2;
//    private int recursiveDepth = 1; // 1:第一次， 2:第二次， 3:第三次或以上
    private boolean isCollection;
    private String fieldName;
    // 每个单体元素的page，是不是表示对象中的集合属性的分页
//    private CmiPagination collectionFieldPagination;不应该是域，应该是局部变量更合适
    private CmiPagination collectionFieldPagination = new CmiPagination();

    public Object fromJson(String json, Type tpeOff) {
        return new Gson().fromJson(json, tpeOff);
    }

    public <T> T fromJson(String json, Class<T> classOfT) {
        return new Gson().fromJson(json, classOfT);
    }

    public String toJsonString(Object object, int depth) {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(appendObjectJsonString(object, depth));
        return stringBuilder.toString();
    }

    public String toPsonString(Object object, int depth, CmiPagination cmiPagination) {
    	//        recursiveDepth = 1;
//        保存需要递归的深度，在toJsonContinue递归中，当深度小于需要递归的深度的时候就停止递归
    	this.customePsonDepth = depth;
        isCollection = object instanceof Collection<?> ? true : false;

        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("{");
        stringBuilder.append("\"page\":");
        stringBuilder.append(JSONObject.toJSONString(cmiPagination));
        stringBuilder.append(",");
        stringBuilder.append("\"data\":");
        stringBuilder.append(appendObjectJsonString(object, depth, cmiPagination));
        stringBuilder.append("}");
        System.out.println(stringBuilder.toString());
        return stringBuilder.toString();
    }

//    属性不分页，好像没地方用
    private String appendObjectJsonString(Object object, int recursivePsonDepth) {
        StringBuilder stringBuilder = new StringBuilder();
        if (object == null) {
            return null;
        } else if (object instanceof Collection<?>) { // Collection集合类型
            stringBuilder.append("[");
            @SuppressWarnings("unchecked")
            Collection<Object> objCollection = (Collection<Object>) object;
            objCollection.forEach(new Consumer<Object>() {
                public void accept(Object subObject) {
                    stringBuilder.append(appendObjectJsonString(subObject, recursivePsonDepth)).append(",");
//                    System.out.println("Collection-->>"+stringBuilder.toString());
                };
            });
            if (stringBuilder.length() > 1) { // 去掉最后一个 ,
                stringBuilder.deleteCharAt(stringBuilder.length() - 1);
            }
            stringBuilder.append("]");
            return stringBuilder.toString();
        } else if (object.getClass().isArray()) { // Array数组类型
            stringBuilder.append("[");
            for (int i = 0; i < Array.getLength(object); i++) {
                stringBuilder.append(appendObjectJsonString(Array.get(object, i), recursivePsonDepth)).append(",");
            }
            if (stringBuilder.length() > 1) {
                stringBuilder.deleteCharAt(stringBuilder.length() - 1);
            }
            stringBuilder.append("]");
            return stringBuilder.toString();
        } else if (object instanceof Map) { // Map类型
            stringBuilder.append("[{");
            @SuppressWarnings("unchecked")
            Map<Object, Object> map = (Map<Object, Object>) object;
            Iterator<Entry<Object, Object>> mapIterator = map.entrySet().iterator();
            while (mapIterator.hasNext()) {
                Entry<Object, Object> current = mapIterator.next();
                stringBuilder.append("\"").append(current.getKey()).append("\"").append(":")
                        .append(toJsonString(current.getValue(), 1)).append(",");
            }
            if (stringBuilder.length() > 1) {
                stringBuilder.deleteCharAt(stringBuilder.length() - 1);
            }
            stringBuilder.append("}]");
            return stringBuilder.toString();
        } else if (object.getClass().getName().startsWith("java")) { // Java JDK 自带 非集合 类实例
            return new Gson().toJson(object);
        } else { // 用户自建类实例
            object = CmiHibernateProxyUtil.deproxy(object);
            stringBuilder.append("{");
            Field[] fields = object.getClass().getDeclaredFields();
            Field.setAccessible(fields, true);
            for (Field field : fields) {
                String fieldName = field.getName();
                Object fieldObject = null;
                try {
                    fieldObject = field.get(object);
                } catch (IllegalArgumentException | IllegalAccessException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                // 控制第Flag层的数据显示，只显示第Flag层的基本属性，集合属性以及引用属性不显示
                if (recursivePsonDepth > 1
                        || (fieldObject != null) && !(fieldObject instanceof Collection<?>)
                                && fieldObject.getClass().getName().startsWith("java")
                        || (fieldObject != null) && !(fieldObject instanceof Collection<?>)
                                && fieldObject.getClass().isArray()) {
                    String fieldJsonString = appendObjectJsonString(fieldObject, recursivePsonDepth - 1);
                    if (fieldJsonString != null) {

                        stringBuilder.append("\"").append(fieldName).append("\"").append(":").append(fieldJsonString)
                                .append(",");
                    }
                }

            }
            if (stringBuilder.length() > 1) {
                stringBuilder.deleteCharAt(stringBuilder.length() - 1);
            }
            stringBuilder.append("}");
            return stringBuilder.toString();
        }
    }

    /**
     *
     * !!!!!!属性分页
     * 1. controller 包装好page，封装到object，psonutil只管使用 问题：object为集合时，page放置问题
     * 思路：把page里的paginationSize beginPagination currentPagination totalPaginations
  * totalRecords设置成静态变量，所有实体类共用，更新page时只需要更新一次
     * 带来问题：如果controller同时被访问，而page只有一个，有可能会导致page数据错乱 2. controller 未包装page,
  * psonutil更新page，再把page封装到json数据中 问题：访问的当前页无法确定 3. controller
     * 包装好page，不封装到object，让page作为第三个参数传进toJson()，psonutil把page封装到返回数据中
     * 问题：返回json数据格式未确定 思路1. page整合到每一个返回的实体类中 思路2. page与返回集合同层次 4. controller
     * 包装好page的当前页信息，传进psonutil，psonutil根据page的当前页进行分页，最后把page封装到返回数据l中
     *
     * 集合： 第一次：使用MyPage成员对集合分页，标记为2 第二次：使用MyPage中的attribute对集合进行分页，标记为3 第三次：操作不变
     * java自带： 第一次：标记为2，操作不变 第二次： 第三次： 自定义： 第一次：标记为2，操作不变 第二次： 第三次：
     *
     *
     *
     * 集合：true 只对当前集合元素分页，集合元素子元素不分页 单体：false 对子元素分页
     *
     * @param object
     * @param currentRecursiveDepth：当前递归的深度
     * @return
     *
     * realDepth用户需要的深度，recursivePsonDepth：需要调用的深度
     *
     */
    @SuppressWarnings("unused")
	private String appendObjectJsonString(Object object, int recursivePsonDepth, CmiPagination cmiPagination) {

		if(object != null) {
//			System.out.println("\n准备输出的对象类型是：" + object.getClass().getName());
//			System.out.println("需要递归recursivePsnDepth的值是：" + recursivePsonDepth);
		}


		StringBuilder stringBuilder = new StringBuilder();
		//      (1) 空
		if (object == null) {
			return null;
		} else if (object instanceof Collection<?>) {

			// (2) Collection集合类型
			stringBuilder.append("[");
			@SuppressWarnings("unchecked")
			Collection<Object> collectionObject = (Collection<Object>) object;
//			System.out.print("已经递归了的深度是：");
//			System.out.println(customePsonDepth - recursivePsonDepth);
//			已经递归的深度
			int recursiveDepth = customePsonDepth - recursivePsonDepth;
			switch (recursiveDepth) {
			case 0:
				Object[] arrayObject = collectionObject.toArray();
				for (int i = 0; i < arrayObject.length; i++) {
					Object subObject = arrayObject[i];
					stringBuilder.append(appendObjectJsonString(subObject, recursivePsonDepth, cmiPagination)).append(",");
				}
				break;
			case 1://对象中的集合属性的处理，最多只取10个数据进行处理
//				System.out.println("处理对象中的集合属性");
				CmiPagination fieldPagination = isCollection ? collectionFieldPagination.getReferencePropertyPaginationMap().get(fieldName) : cmiPagination.getReferencePropertyPaginationMap().get(fieldName);
				Object[] fieldArray = collectionObject.toArray();
//				先暂时使用测试数据
				for (int i = 0; i < 10 && i < collectionObject.size(); i++) {
					Object fieldObject = fieldArray[i];
					stringBuilder.append(appendObjectJsonString(fieldObject, recursivePsonDepth, fieldPagination)).append(",");
				}
				break;

			/*
			 * default: collectionObject.forEach(new Consumer<Object>() {
			 *
			 * @Override public void accept(Object t) {
			 * System.out.println("？？？？？？？这个方法不懂！！！");
			 * stringBuilder.append(appendObjectJsonString(t, recursivePsonDepth,
			 * cmiPagination)).append(","); } }); break;
			 */
			}

			if (stringBuilder.length() > 1) { // 去掉最后一个 ,
				stringBuilder.deleteCharAt(stringBuilder.length() - 1);
			}
			stringBuilder.append("]");
			return stringBuilder.toString();


		} else if (object.getClass().isArray()) {


			// (3) Array数组类型
//            stringBuilder.append("[");
//            for (int i = 0; i < Array.getLength(object); i++) {
//                stringBuilder.append(toJsonContinue(Array.get(object, i), depth)).append(",");
//            }
//            if (stringBuilder.length() > 1) {
//                stringBuilder.deleteCharAt(stringBuilder.length() - 1);
//            }
//            stringBuilder.append("]");
//            return stringBuilder.toString();
		} else if (object instanceof Map) {


			//(4) Map类型
//            stringBuilder.append("[{");
//            @SuppressWarnings("unchecked")
//            Map<Object, Object> map = (Map<Object, Object>) object;
//            Iterator<Map.Entry<Object, Object>> mapIterator = map.entrySet().iterator();
//            while (mapIterator.hasNext()) {
//                Entry<Object, Object> current = mapIterator.next();
//                stringBuilder.append("\"").append(current.getKey()).append("\"").append(":")
//                        .append(toJson(current.getValue())).append(",");
//            }
//            if (stringBuilder.length() > 1) {
//                stringBuilder.deleteCharAt(stringBuilder.length() - 1);
//            }
//            stringBuilder.append("}]");
//            return stringBuilder.toString();
		} else if (object.getClass().getName().startsWith("java")) {


			//(5) Java JDK 自带 非集合 类实例
//			System.out.println("!!!!!!" + object.getClass().getName() + "是java自定义的类");
			return new Gson().toJson(object);

		} else {


			// (6) 用户自建类实例
//            if (recursiveDepth == 1)
//                recursiveDepth = 2;
			object = CmiHibernateProxyUtil.deproxy(object);
			stringBuilder.append("{");
			if (this.customePsonDepth == recursivePsonDepth) {
				stringBuilder.append("\"page\":");
				stringBuilder.append(JSONObject.toJSONString(collectionFieldPagination));
				stringBuilder.append(",");
			}
			Field[] fields = object.getClass().getDeclaredFields();
			Field.setAccessible(fields, true);
			for (Field field : fields) {
				String fieldName = field.getName();
//				System.out.println("******393" + fieldName);
				this.fieldName = fieldName;
				Object fieldObject = null;
				try {
					fieldObject = field.get(object);
				} catch (IllegalArgumentException | IllegalAccessException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				// 控制第Flag层的数据显示，只显示第Flag层的基本属性，集合属性以及引用属性不显示
				if (recursivePsonDepth > 1
						|| (fieldObject != null) && !(fieldObject instanceof Collection<?>) && fieldObject.getClass().getName().startsWith("java")
						|| (fieldObject != null) && !(fieldObject instanceof Collection<?>) && fieldObject.getClass().isArray()) {

//					对象中的集合数据递归的深度降低一个
					String fieldJsonString = appendObjectJsonString(fieldObject, recursivePsonDepth - 1, cmiPagination);

					if (fieldJsonString != null) {
						stringBuilder.append("\"").append(fieldName).append("\"").append(":").append(fieldJsonString).append(",");
					}
				}
			}
			if (stringBuilder.length() > 1) {
				stringBuilder.deleteCharAt(stringBuilder.length() - 1);
			}
			stringBuilder.append("}");
			return stringBuilder.toString();
		}
		return null;
	}
}
